#include "stdafx.h"


#include <stdio.h>
#include <stdlib.h>
#include <string.h> 

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
   
#include <map>
#include <vector>
 
#include "./fore_rtdb.h"
#include "./base.h"
 
#include "./rtdbFun.h"
 

 

#include "./rtdb_fun.h"
 
  
 

bool TDbFun::put_yx(char * appName, time_t updateTime, char * stringkey, unsigned char val)
{
	if( stringkey == NULL ) return false;

	FORE_YX_POINT * pYx = (FORE_YX_POINT*)FindRec_stringkey(FORE_YX_POINT_NO, stringkey);  
	if( pYx == NULL ) {
		base::my_printf(" no find Yx_KEY : stringkey= %s \n", stringkey);
		return false ; 
	}  
 
	unsigned char yx_val = val;
	if( pYx->jx ) {
		yx_val != yx_val;
	}
 
	
	int t = updateTime;
	if( t <= 0 )  t = time(NULL);

	strcpy(pYx->appName, appName);

	//base::my_printf(" devid=%d, fid=%d  pYx->CurYxRTVal == yxval val = %d \n", inner_dev_addr, data_fld , (int)yx_val ); 
	if( pYx->LastTime > 0 ) 
	{
		pYx->LastTime   = t;

		if(pYx->CurYxRTVal == yx_val) {
			//base::my_printf(" pYx->CurYxRTVal == yxval val = %d \n", yxval ); 
		}
		else
		{
			pYx->BWCount ++; 

			pYx->PreYxRTVal = pYx->CurYxRTVal; 
			pYx->CurYxRTVal = yx_val;   
		}
	}
	else
	{
		pYx->CurYxRTVal = yx_val;
		pYx->PreYxRTVal = yx_val; 

		pYx->FirstTime = t;
		pYx->LastTime   = t;
	}  
	return true ;
}
 

bool TDbFun::put_yc(char * appName, time_t updateTime, char * stringkey, float val)
{ 	
	if( stringkey == NULL ) return false;
	 
	FORE_YC_POINT * pYc = (FORE_YC_POINT*)FindRec_stringkey(FORE_YC_POINT_NO, stringkey);  
	if( pYc == NULL ) {
		base::my_printf(" no find Yc_KEY : stringkey=%s  \n", stringkey );
		return  false; 
	} 
  
	float  tmpVal = pYc->CurYcValue;
	
	if( pYc->coff == 0 )
	{
		tmpVal = val;
	}
	else
	{
		tmpVal = pYc->coff*val + pYc->offset; 
	}

	/*if( pYc->min_val != pYc->max_val ) {
		if( tmpVal <= pYc->min_val ) return false;
		if( tmpVal >= pYc->max_val ) return false;
	}*/
		 
	strcpy(pYc->appName, appName);

	int t = updateTime;
	if( t <= 0 )  t = time(NULL);

	if( pYc->LastUpdateTime > 0 ) 
	{  
		pYc->PreYcValue = pYc->CurYcValue; 
		pYc->CurYcValue = tmpVal; 
		pYc->LastUpdateTime   = t; 
	}
	else
	{
		pYc->CurYcValue = tmpVal;
		pYc->PreYcValue = tmpVal; 

		pYc->LastUpdateTime   = t;
	}  
	 

	return true;
}


bool TDbFun::get_paramval_by_key( char * chrParamKey, char * chrVal )
{  
	if( chrParamKey == NULL || chrVal == NULL ) return false;
	if( strlen(chrParamKey) <= 0  ) return false;
  
	tHandle handle = OpenLib(FORE_PARAM_CFG_NO); 
	if( !IsHandleValid(handle) ) return false;
 
	FORE_PARAM_CFG  rec;
	bool ret = ReadFirst(handle, (char*)&rec, sizeof(FORE_PARAM_CFG )); 
	while( ret )
	{   
		//printf("param_name=%s, val=%s \n ", rec.param_name, rec.param_val);	 
		if( strcmp(rec.param_name, chrParamKey) == 0 ) {
			strcpy(chrVal, rec.param_val);
			return true;
		}
		ret = ReadNext(handle, (char*)&rec, sizeof(FORE_PARAM_CFG ));
	} 

	CloseLib(handle);  

	return false; 
}




bool TDbFun::GetDevs_ByDevType(char * chrDevType, std::vector<FORE_DEV_DICT> & aryDev)
{ 
	if( chrDevType == NULL  ) return false; 

	tHandle handle = OpenLib(FORE_DEV_INFO_NO);
	if( !IsHandleValid(handle) ) {
		base::my_printf("FORE_DEV_INFO is InValid \n");
		return false;
	} 
	FORE_DEV_DICT  rec;
	bool ret = ReadFirst(handle, (char*)&rec, sizeof(FORE_DEV_DICT )); 
	while( ret )
	{     
		//base::my_printf("%s : %s \n", rec.deviceType, strDevType.c_str());

		if( strcmp(rec.deviceType, chrDevType ) == 0 ) {   
			aryDev.push_back( rec ); 
		} 
		ret = ReadNext(handle, (char*)&rec, sizeof(FORE_DEV_DICT ));
	} 
	 
	CloseLib(handle);


	return true;
}
   

int _sort_mea_template_fun(const void * a, const void * b)
{
	FORE_MEA_TEMPLATE * p1 = (FORE_MEA_TEMPLATE*) a;
	FORE_MEA_TEMPLATE * p2 = (FORE_MEA_TEMPLATE*) b;
	 
	if( strcmp(p1->serviceid , p2->serviceid ) > 0 ) {
		return 1;
	}
	else if( p1->serviceid < p2->serviceid ) {
		return -1;
	}
	else return  strcmp(p1->propertyName, p2->propertyName) ; 
} 

void TDbFun::query_meaTempl_by_devType(char* dev_type, std::vector<FORE_MEA_TEMPLATE> & aryMeaTemplInfo)
{
	if( dev_type == NULL  ) {
		base::my_printf("dev_type == null \n" );  
		return;
	}
 

	tHandle handle = OpenLib(FORE_MEA_TEMPLATE_NO);
	if( !IsHandleValid(handle) ) {
		base::my_printf("FORE_MEA_TEMPLATE_NO is InValid \n");
		return  ;
	}
	FORE_MEA_TEMPLATE  rec;
	bool ret = ReadFirst(handle, (char*)&rec, sizeof(FORE_MEA_TEMPLATE));  
	while( ret )
	{      
		if( strcmp(rec.dev_type,dev_type)==0  ) { 
			aryMeaTemplInfo.push_back( rec ); 
		} 
		
		ret = ReadNext(handle, (char*)&rec, sizeof(FORE_MEA_TEMPLATE));
	}   
	CloseLib(handle);

	if( aryMeaTemplInfo.size() > 1 ) 
		qsort( aryMeaTemplInfo.data(), aryMeaTemplInfo.size(), sizeof(FORE_MEA_TEMPLATE), _sort_mea_template_fun);

	return ;
}


void TDbFun::query_meaTempl_by_devType(char* dev_type, std::map<string, ARYMEATEMPLATE> & mapServiceID2Meatempl)
{
	if( dev_type == NULL  ) {
		base::my_printf("dev_type == null \n" );  
		return;
	}
 

	tHandle handle = OpenLib(FORE_MEA_TEMPLATE_NO);
	if( !IsHandleValid(handle) ) {
		base::my_printf("FORE_MEA_TEMPLATE_NO is InValid \n");
		return  ;
	}
	FORE_MEA_TEMPLATE  rec;
	
	bool ret = ReadFirst(handle, (char*)&rec, sizeof(FORE_MEA_TEMPLATE));  
	while( ret )
	{      
		if( strcmp(rec.dev_type,dev_type)==0  ) { 

			std::map<string, ARYMEATEMPLATE>::iterator it = mapServiceID2Meatempl.find( rec.serviceid );
			if(it  == mapServiceID2Meatempl.end()) {
				ARYMEATEMPLATE   ary;
				ary.push_back( rec );

				mapServiceID2Meatempl.insert( pair<string, ARYMEATEMPLATE>(rec.serviceid, ary) );
			}
			else {
				ARYMEATEMPLATE  & ary =  it->second;
				ary.push_back( rec );
			} 
		} 
		
		ret = ReadNext(handle, (char*)&rec, sizeof(FORE_MEA_TEMPLATE));
	}   
	CloseLib(handle);
	 
	return ;
}


bool TDbFun::get_mea_template_by_devTypeAndfieldName( char * dev_type, char* field_name, FORE_MEA_TEMPLATE & mea)
{
	if( dev_type == NULL || strlen(dev_type) <= 0 || field_name == NULL ) return false;


	char  chrKey[64] = {0};
	sprintf(chrKey, "%s:%s", dev_type, field_name);

	FORE_MEA_TEMPLATE * pMea = (FORE_MEA_TEMPLATE*)FindRec_stringkey(FORE_MEA_TEMPLATE_NO, chrKey);
	if( pMea ) {
		memcpy(&mea, pMea, sizeof(FORE_MEA_TEMPLATE));
		return true;
	} 
	return false;
}
 


void TDbFun::load_rtdata( char * nodeID, ARYMEATEMPLATE & ary, std::vector<RT_DATA> & rtData)
{
	if( nodeID == NULL ) return;
	
	for( int i=0; i<ary.size(); i++ )
	{
		FORE_MEA_TEMPLATE & meaInfo = ary[i];
		
		char  chrKey[64] = {0};
		sprintf(chrKey, "%s:%s", nodeID, meaInfo.propertyName);
		  
		RT_DATA  rt_data; 
		
		strcpy(rt_data.dev_code,	nodeID);
		strcpy(rt_data.field_name,	meaInfo.propertyName);
		strcpy(rt_data.dev_type,    meaInfo.dev_type);
		strcpy(rt_data.serverId,    meaInfo.serviceid);
		 
		if( strstr(meaInfo.serviceid, "Analog") != NULL || strstr(meaInfo.serviceid, "Accumulator") != NULL ) {  //yc
			FORE_YC_POINT * pYc = (FORE_YC_POINT*)FindRec_stringkey(FORE_YC_POINT_NO, chrKey);  
			if( pYc == NULL ) continue; 

			
			rt_data.data_type       = DATA_CATEGORY_YC;
			rt_data.fval		= pYc->CurYcValue;
			rt_data.update_time = pYc->LastUpdateTime;
			 
		}
		else if( strstr(meaInfo.serviceid, "Discrete") != NULL ) {  //yx
			FORE_YX_POINT * pYx = (FORE_YX_POINT*)FindRec_stringkey(FORE_YX_POINT_NO, chrKey);  
			if( pYx == NULL )  continue; 
			
			 
			rt_data.data_type       = DATA_CATEGORY_YX;
			rt_data.fval		= (int)pYx->CurYxRTVal;
			rt_data.update_time = pYx->LastTime;
		 
		}
		else {
			base::my_printf("serviceid=%s is InValid \n", meaInfo.serviceid);

			continue;
		} 
		
		rtData.push_back( rt_data );
	}
}


void TDbFun::load_rtdata_bychanged( std::vector<RT_DATA> & rtDataOld, std::vector<RT_DATA> & rtDataChanged, int readDataType )  ////0:all, 1:yc, 2:yx, 3:changeYxYc
{ 
	if( rtDataOld.size() <= 0 ) return;
 
	for( int i=0; i<rtDataOld.size(); i++ )
	{
		RT_DATA & rt_old = rtDataOld[i];   
		
		RT_DATA  rt_new;
		strcpy(rt_new.dev_code, rt_old.dev_code);
		strcpy(rt_new.field_name, rt_old.field_name);
		strcpy(rt_new.dev_type, rt_old.dev_type); 
		strcpy(rt_new.serverId,    rt_old.serverId);
		rt_new.data_type		= rt_old.data_type;
 	
		char  chrKey[64] = {0};
		sprintf(chrKey, "%s:%s",rt_old.dev_code, rt_old.field_name);

		if( rt_old.data_type == DATA_CATEGORY_YX ) {  //yx
			
			if( readDataType == 1 ) continue;  

			FORE_YX_POINT * pYx = (FORE_YX_POINT*)FindRec_stringkey(FORE_YX_POINT_NO, chrKey);  
			if( pYx == NULL )  {
				base::my_printf( "Yx rec not find : %s \n",chrKey); 
				continue; 
			}
			
			if( pYx->LastTime <= 0 ) continue;

			//if( rt_old.bSendChangeData ) 
//base::my_printf( "yx = %d , %d  \n",rt_old.fval, pYx->CurYxRTVal); 
			{ 
				if( pYx->CurYxRTVal != (unsigned char)rt_old.fval )  {
					rt_new.fval			= (int)pYx->CurYxRTVal;
					rt_new.update_time 	= pYx->LastTime;  

//base::my_printf( "\n\n -----------------------key = %s : append change yx:  %d -> %d \n" , chrKey, (int)rt_old.fval, (int)rt_new.fval); 
					
					rtDataChanged.push_back( rt_new );
				}  
			}
			
			rt_old.fval		= pYx->CurYxRTVal;
			rt_old.update_time 	= pYx->LastTime;
		}
		else {
			if( readDataType == 2 ) continue;
 

//printf("\n\n\n=========================read yc %d \n\n\n");

			FORE_YC_POINT * pYc = (FORE_YC_POINT*)FindRec_stringkey(FORE_YC_POINT_NO, chrKey);  
			if( pYc == NULL ) {
				base::my_printf( "Yc rec not find : %s \n", chrKey); 
				continue; 
			} 

			if( pYc->LastUpdateTime <= 0 ) continue;
		//	if( pYc->zf_type != 0 ) continue; //�Ƿ�ת����ƽ̨ ��Ĭ��Ϊ0 ת�������ǵ���ʷ��¼���� ֵΪ1�� ��ת��

			//if( rt_old.bSendChangeData )  
			{
				float   ff = fabs(pYc->CurYcValue - rt_old.fval);
				if(  ff > 0.05 )  {

					float f1 = fabs( ff * 1.0 / pYc->CurYcValue );
					float f2 = fabs( pYc->CurYcValue - rt_old.fval );

					if( pYc->up_step == 0 &&  pYc->low_step == 0  ){  //
						if( strcmp(rt_new.field_name, "PhV_phsA") == 0 || strcmp(rt_new.field_name, "PhV_phsB") == 0
						     || strcmp(rt_new.field_name, "PhV_phsC") == 0 || strcmp(rt_new.field_name, "PhV_phsN") == 0 ) 
						{ 
							if( f1 >= 0.02 ) {
								rt_new.fval		= pYc->CurYcValue;
								rt_new.update_time  	= pYc->LastUpdateTime;  
								rtDataChanged.push_back( rt_new );
							}   
						}
						else if( strcmp(rt_new.field_name, "A_phsA") == 0 || strcmp(rt_new.field_name, "A_phsB") == 0
						          || strcmp(rt_new.field_name, "A_phsC") == 0 || strcmp(rt_new.field_name, "A_phsN") == 0) 
						{  
							if(  (f2 >= 10) || (f1 >= 0.1) ) {
								rt_new.fval		= pYc->CurYcValue;
								rt_new.update_time  	= pYc->LastUpdateTime;  
								rtDataChanged.push_back( rt_new );
							}   
						}
						else {
							if( f1 >= 0.1 ) {
								rt_new.fval		= pYc->CurYcValue;
								rt_new.update_time  	= pYc->LastUpdateTime;  
								rtDataChanged.push_back( rt_new );
							}  
						}
						
						
					}
					else {
						if(   fabs(pYc->CurYcValue-rt_old.fval) > pYc->up_step ) {   //Ŀǰֻ��һ��step
							rt_new.fval		        = pYc->CurYcValue;
							rt_new.update_time  	= pYc->LastUpdateTime; 
						
							rtDataChanged.push_back( rt_new ); 
						}
					} 
					
				}
			}
			
			rt_old.fval		= pYc->CurYcValue;
			rt_old.update_time 	= pYc->LastUpdateTime;
		}  
	}
}


void TDbFun::GetDevs(std::vector<FORE_DEV_DICT> & aryDev)
{
	tHandle handle = OpenLib(FORE_DEV_INFO_NO);
	if( !IsHandleValid(handle) ) {
		base::my_printf("FORE_DEV_INFO is InValid \n");
		return  ;
	}
	FORE_DEV_DICT  rec;
	bool ret = ReadFirst(handle, (char*)&rec, sizeof(FORE_DEV_DICT )); 
	while( ret )
	{     		 
		aryDev.push_back( rec ); 
		 
		ret = ReadNext(handle, (char*)&rec, sizeof(FORE_DEV_DICT ));
	} 
	CloseLib(handle);
}

void TDbFun::remove_mev_by_dev_type(char* dev_type)
{
	if( dev_type == NULL ) return ;
 
	std::vector<string>  aryDevInfo;
	std::vector<string>  aryFieldName;
	//dev 
	tHandle handle = OpenLib(FORE_DEV_INFO_NO);
	if( !IsHandleValid(handle) ) {
		base::my_printf("FORE_DEV_INFO is InValid \n");
		return  ;
	}
	FORE_DEV_DICT  rec;
	bool ret = ReadFirst(handle, (char*)&rec, sizeof(FORE_DEV_DICT )); 
	while( ret )
	{     		 
		if( strcmp(dev_type, rec.deviceType) == 0 ) { 
			Delete_key( FORE_DEV_INFO_NO, rec.dev_nodeID );
			aryDevInfo.push_back(rec.dev_nodeID); 
		}
		 
		ret = ReadNext(handle, (char*)&rec, sizeof(FORE_DEV_DICT ));
	} 
	CloseLib(handle);
 
	//mea_templ
	handle = OpenLib(FORE_MEA_TEMPLATE_NO);
	if( !IsHandleValid(handle) ) {
		base::my_printf("FORE_MEA_TEMPLATE is InValid \n");
		return  ;
	}
	FORE_MEA_TEMPLATE  meaRec;
	ret = ReadFirst(handle, (char*)&meaRec, sizeof(FORE_MEA_TEMPLATE)); 
	while( ret )
	{     		 
		if( strcmp(dev_type, meaRec.dev_type) == 0 ) {
			//base::my_printf("remove dev_type=%s, name=%s \n", dev_type, meaRec.propertyName);  

			char  chrKey[64] = {0};
			sprintf(chrKey, "%s:%s", dev_type, meaRec.propertyName);
			Delete_key( FORE_MEA_TEMPLATE_NO, chrKey );
 

			aryFieldName.push_back(meaRec.propertyName);
			 
		}
		 
		ret = ReadNext(handle, (char*)&meaRec, sizeof(FORE_MEA_TEMPLATE));
	} 
	CloseLib(handle);

  
	for( int i=0; i<aryDevInfo.size(); i++ )
	{
		for( int j=0; j<aryFieldName.size(); j++ )
		{
			char  chrKey[64] = {0};
			sprintf(chrKey, "%s:%s", aryDevInfo[i].c_str(), aryFieldName[j].c_str());
 
			Delete_key(FORE_YX_POINT_NO, chrKey );
			Delete_key(FORE_YC_POINT_NO, chrKey );
		} 
	}	

	 
}


void TDbFun::GetDevType(std::vector<FORE_DEV_TYPE> & aryDevType)
{
	tHandle handle = OpenLib(FORE_DEV_TYPE_NO);
	if( !IsHandleValid(handle) ) {
		base::my_printf("FORE_DEV_TYPE is InValid \n");
		return  ;
	}
	FORE_DEV_TYPE  rec;
	bool ret = ReadFirst(handle, (char*)&rec, sizeof(FORE_DEV_TYPE )); 
	while( ret )
	{     		 
		if( rec.protocolType != NULL && rec.deviceType != NULL )
			aryDevType.push_back( rec ); 
		 
		ret = ReadNext(handle, (char*)&rec, sizeof(FORE_DEV_TYPE ));
	} 
	CloseLib(handle);
}

bool TDbFun::set_rtdb_version( unsigned int ver )
{
	if( ver <= 0 ) return false;
	
	FORE_PARAM_CFG   param; 
	strcpy(param.param_name,  "RTDB_VERSION");
	sprintf(param.param_val, "%d", ver);

	if( !UpdateRec_stringkey_Ex(FORE_PARAM_CFG_NO, "RTDB_VERSION", (char*)&param, sizeof(FORE_PARAM_CFG)  ) )
		return false;

	return true; 
}

int  TDbFun::get_rtdb_Version()
{
	int rtdbVer = 0;
	char chr_rtdb_ver[128]={0};

	if( get_paramval_by_key( "RTDB_VERSION", chr_rtdb_ver ) )
	{
		//printf("ver=%s \n ", chr_rtdb_ver);
		rtdbVer = atoi( chr_rtdb_ver );
	}

	return rtdbVer;
}


